package loader

import (
	"github.com/spf13/viper"
	"go.uber.org/zap"
	"xincan.com.cn/tarot-go/internal/common/constants"
	"xincan.com.cn/tarot-go/internal/common/types"
	"xincan.com.cn/tarot-go/internal/components/logging"
	"xincan.com.cn/tarot-go/internal/config/factory"
)

// remoteApplicationConfigLoader
// Title 				remoteApplicationConfigLoader
// Description 			全局参数配置: 读取远程配置
// Author  				alittlexincan@163.com 					2024/07/22 11:36
// Update  				alittlexincan@163.com 					2024/07/22 11:36
type remoteApplicationConfigLoader struct {

	// localViper 本地配置实例
	localViper *viper.Viper

	// logger 日志实例
	logger *logging.TraceLogger

	// provider 配置提供者
	provider constants.ProviderType

	// instance 配置实例
	instance factory.RemoteApplicationConfigLoaderFactory
}

// RemoteApplicationConfigLoaderBuilder
// Title 				RemoteApplicationConfigLoaderBuilder
// Description 			创建远程参数配置构建器
// Author  				alittlexincan@163.com 					2024/07/22 11:36
// Update  				alittlexincan@163.com 					2024/07/22 11:36
type RemoteApplicationConfigLoaderBuilder struct {
	*remoteApplicationConfigLoader
}

// NewRemoteApplicationConfigLoaderBuilder
// Title    			NewRemoteApplicationConfigLoaderBuilder
// Description   		初始化远程参数配置构建器
// Author      			alittlexincan@163.com       									2024/07/17 11:36
// Update    			alittlexincan@163.com       									2024/07/17 11:36
// Return    			*RemoteApplicationConfigLoaderBuilder     						返回远程参数配置构建器
func NewRemoteApplicationConfigLoaderBuilder() *RemoteApplicationConfigLoaderBuilder {
	return &RemoteApplicationConfigLoaderBuilder{
		remoteApplicationConfigLoader: &remoteApplicationConfigLoader{},
	}
}

// WithLocalViper
// Title 				WithLocalViper
// Description 			构造器: 配置本地参数配置实例
// Author      			alittlexincan@163.com       									2024/07/17 11:36
// Update    			alittlexincan@163.com       									2024/07/17 11:36
// Param    			localViper 								*viper.Viper			本地参数配置实例
// Return    			*RemoteApplicationConfigLoaderBuilder     						返回远程参数配置构建器
func (builder *RemoteApplicationConfigLoaderBuilder) WithLocalViper(localViper *viper.Viper) *RemoteApplicationConfigLoaderBuilder {
	builder.localViper = localViper
	builder.provider = constants.ProviderType(localViper.GetString("application.config.provider"))
	return builder
}

// WithLogger
// Title 				WithLogger
// Description 			构造器: 配置日志实例
// Author      			alittlexincan@163.com       									2024/07/17 11:36
// Update    			alittlexincan@163.com       									2024/07/17 11:36
// Param    			logger 								*logging.TraceLogger 		日志实例
// Return    			*RemoteApplicationConfigLoaderBuilder     						返回远程参数配置构建器
func (builder *RemoteApplicationConfigLoaderBuilder) WithLogger(logger *logging.TraceLogger) *RemoteApplicationConfigLoaderBuilder {
	builder.logger = logger
	return builder
}

// Build
// Title 				Build
// Description 			构造器: 构建远程参数配置实例
// Author      			alittlexincan@163.com       			2024/07/17 11:36
// Update    			alittlexincan@163.com       			2024/07/17 11:36
// Return    			*RemoteApplicationConfigLoader			远程配置参数实例
func (builder *RemoteApplicationConfigLoaderBuilder) Build() *RemoteApplicationConfigLoaderBuilder {
	builder.ConfigLoad()
	return builder
}

// ConfigLoad
// Title 				ConfigLoad
// Description 			加载远程配置信息, 合并到本地参数配置信息
// Author      			alittlexincan@163.com       			2024/07/17 11:36
// Update    			alittlexincan@163.com       			2024/07/17 11:36
// Return    			*viper.Viper     						远程参数配置实例
func (remote *remoteApplicationConfigLoader) ConfigLoad() *viper.Viper {

	// 1. 如果是本地配置,说明没有要加载的远程配置 则返回 nil
	if remote.provider == "" || remote.provider == constants.ProviderConfigNone {
		remote.logger.Error("暂无加载远程配置: 当前配置类型为", zap.Any("provider", remote.provider))
		return nil
	}
	remote.logger.Info("加载远程配置信息: 当前配置类型为", zap.Any("provider", remote.provider))
	// 2. 获取本地配置信息
	var service *types.Service
	if err := remote.localViper.Unmarshal(&service); err != nil {
		remote.logger.Error("加载远程配置信息失败", zap.Error(err))
		return nil
	}
	// 3. 获取远程配置实例, 合并远程配置信息
	remoteViper, instance := factory.InstanceFactory.WithProvider(remote.provider).WithLogger(remote.logger).WithService(service).Build().ConfigLoad()
	for key, value := range remoteViper.AllSettings() {
		remote.localViper.Set(key, value)
	}
	remote.logger.Info("合并远程配置信息成功", zap.Any("remote", remote.localViper.AllSettings()))
	remote.instance = instance
	return remoteViper
}

// WatchRemoteConfigLoad
// Title 				WatchRemoteConfigLoad
// Description 			监听远程配置信息, 监听到配置信息变化, 则更新本地参数配置信息
// Author      			alittlexincan@163.com       											2024/07/17 11:36
// Update    			alittlexincan@163.com       											2024/07/17 11:36
// Param    			callback 					factory.ConfigWatchRemoteConfigLoadFunc 	监听回调函数
func (remote *remoteApplicationConfigLoader) WatchRemoteConfigLoad(callback factory.ConfigWatchRemoteConfigLoadFunc) {
	if remote.provider == "" || remote.provider == constants.ProviderConfigNone || remote.instance == nil {
		remote.logger.Error("监听远程配置失败: 当前配置中心类型为", zap.Any("provider", remote.provider))
		return
	}
	remote.instance.WatchRemoteConfigLoad(func(watchViper *viper.Viper) {
		callback(watchViper)
	})
}
